# common setup
ERL_TOP           = /home/d/den/cean/erlang
ERL_INTERFACE_TOP = $(ERL_TOP)/lib/erl_interface-3.5.5.3
ERTS_TOP          = $(ERL_TOP)/erts-5.5.4

NUL        = /dev/null
LIBFFI_DIR = c_src/libffi
DLL_OR_SO  = so
CC         = gcc
EI_LIB_PATH   = $(ERL_INTERFACE_TOP)/lib
ERTS_LIB_PATH = $(ERTS_TOP)/linux-x86/lib

include libffi_config/ffi.mk

LIBFFI_SRC = $(patsubst %, c_src/libffi/%, $(FFI_SOURCES))
LIBFFI_SRC += c_src/libffi/src/types.c

# common stuff
SRC          = c_src/driver_libffi.c
ERLS         = $(wildcard src/*.erl)
BEAMS        = $(patsubst src/%.erl, ebin/%.beam, $(ERLS))
RELEASE_DIR  = build
DEBUG_DIR    = build.debug
EBIN_DIR     = ebin
#LIBFFI_SRC   = $(wildcard $(LIBFFI_DIR)/*.c)
LIBFFI_RELEASE_OBJ = $(patsubst %, build/%.o, $(basename $(notdir $(LIBFFI_SRC))))
LIBFFI_DEBUG_OBJ = $(patsubst %, build.debug/%.o, $(basename $(notdir $(LIBFFI_SRC))))
RELEASE_DLL  = driver_libffi.$(DLL_OR_SO)
DEBUG_DLL    = $(RELEASE_DLL)
INCLUDE_DIR  = -Ilibffi_config/include -Ilibffi_config
INCLUDE_DIR += -I$(ERL_INTERFACE_TOP)/include -I$(ERTS_TOP)/include
LIBS_RELEASE = $(EI_LIB_PATH)/libei.a $(ERTS_LIB_PATH)/liberts.a
LIBS_DEBUG   = $(LIBS_RELEASE)

# portable 'mkdir -p' (windows' mkdir doesn't support -p)
mkdir = @mkdir $(1) 2> $(NUL) || echo

export CC DLL_OR_SO NUL

release: bin/$(RELEASE_DLL) $(BEAMS)
debug: bin.debug/$(DEBUG_DLL) $(BEAMS)
all: release debug build_test examples

$(EBIN_DIR)/%.beam: src/%.erl $(wildcard src/*.hrl)
	$(call mkdir, $(EBIN_DIR))
	erlc -o $(EBIN_DIR) $<

clean:
	rm -rf $(BEAMS)
	rm -rf build
	rm -rf build.debug
	rm -rf bin
	rm -rf bin.debug
	cd tests && $(MAKE) clean
	cd examples && $(MAKE) clean

build_test:
	cd tests && $(MAKE)

test: release build_test
	cd tests && erl -noshell -pa build -run runtests main $(TEST)

testd: debug build_test
	cd tests && erl -noshell -pa build -run runtests main debug $(TEST)

testall: all test testd

examples:
	cd examples && $(MAKE)

DEBUG_FLAGS = -DDEBUG
RELEASE_FLAGS = -O2

# -ansi -pedantic ?
CFLAGS = -fPIC -Wall -W -Wconversion -Wshadow -Wcast-qual -Wwrite-strings

bin.debug/$(DEBUG_DLL): $(SRC) $(LIBFFI_DEBUG_OBJ) $(wildcard c_src/*.h)
	@mkdir -p bin.debug
	$(CC) $(CFLAGS) -shared $(INCLUDE_DIR) $(DEBUG_FLAGS) $(SRC) $(LIBFFI_DEBUG_OBJ) $(LIBS_DEBUG) -o $@

bin/$(RELEASE_DLL): $(SRC) $(LIBFFI_RELEASE_OBJ) $(wildcard c_src/*.h)
	@mkdir -p bin
	$(CC) $(CFLAGS) -shared $(INCLUDE_DIR) $(RELEASE_FLAGS) $(SRC) $(LIBFFI_RELEASE_OBJ) $(LIBS_RELEASE) -o $@

VPATH += $(dir $(LIBFFI_SRC))

build/%.o: %.c | build
	$(CC) $(CFLAGS) -c $(INCLUDE_DIR) $^ -o $@

build.debug/%.o: %.c | build.debug
	$(CC) $(CFLAGS) -c $(INCLUDE_DIR) $^ -o $@

build/%.o: %.S | build
	$(CC) -c $(INCLUDE_DIR) $^ -o $@

build.debug/%.o: %.S | build.debug
	$(CC) -c $(INCLUDE_DIR) $^ -o $@

build:
	mkdir -p build

build.debug:
	mkdir -p build.debug

.PHONY: all debug release clean build_test test testd testall examples
